package com.spring.demo3.eg1;

import org.springframework.cglib.core.DefaultNamingPolicy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.NoOp;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author vhans
 */
@SuppressWarnings("DuplicatedCode")
public class Test {
    /**
     * jdk代理：给接口创建代理
     */
    @org.junit.Test
    public void test1() {
        Service service = new Service();
        Object proxy = Proxy.newProxyInstance(
                service.getClass().getClassLoader(),
                new Class[]{IService1.class, IService2.class},
                new CostTimeInvocationHandler(service));
        print(proxy);
    }

    /**
     * cglib代理：给接口创建代理
     * 相当于public class IService1$$EnhancerByCGLIB$$47f842ce implements IService1, IService2
     */
    @org.junit.Test
    public void test2() {
        Object proxy = CostTimeInterfaceProxy.createProxy(new Class[]{IService1.class, IService2.class});
        if (proxy instanceof IService1) {
            ((IService1) proxy).m1();
        }
        if (proxy instanceof IService2) {
            ((IService2) proxy).m2();
        }
        //看一下代理对象的类型
        System.out.println(proxy.getClass());
        //看一下代理类实现的接口
        System.out.println("创建代理类实现的接口如下：");
        for (Class<?> cs : proxy.getClass().getInterfaces()) {
            System.out.println(cs);
        }
    }

    /**
     * cglib代理：给接口和类同时创建代理
     * 相当于public class Service$$EnhancerByCGLIB$$a4a82bda extends Service implements IService1, IService2
     */
    @org.junit.Test
    public void test3() {
        // 获取Service的代理
        Object proxy = CostTimeProxy.createProxy(new Service(), new Class[]{IService1.class, IService2.class});
        print(proxy);
        //看一下代理类实现的接口
        System.out.println("创建代理类实现的接口如下：");
        for (Class<?> cs : proxy.getClass().getInterfaces()) {
            System.out.println(cs);
        }
    }

    // 接口NamingPolicy表示生成代理类的名字的策略，通过 Enhancer.setNamingPolicy 方法设置命名策略
    @org.junit.Test
    public void test4() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Service.class);
        enhancer.setCallback(NoOp.INSTANCE);
        // 设置命名规则
        enhancer.setNamingPolicy(new DefaultNamingPolicy() {
            @Override
            protected String getTag() {
                return "-Vhans-";
            }
        });
        Object proxy = enhancer.create();
        System.out.println(proxy.getClass());
    }

    private void print(Object proxy) {
        //判断代理对象是否是Service类型的，肯定是true
        System.out.printf("proxyObject instanceof Service = %s%n", proxy instanceof Service);
        //判断代理对象是否是IService1类型的，肯定是true
        System.out.printf("proxyObject instanceof IService1 = %s%n", proxy instanceof IService1);
        //判断代理对象是否是IService2类型的，肯定是true
        System.out.printf("proxyObject instanceof IService2 = %s%n", proxy instanceof IService2);

        //将代理转换为IService1类型
        IService1 service1 = (IService1) proxy;
        service1.m1();

        //将代理转换为IService2类型
        IService2 service2 = (IService2) proxy;
        service2.m2();
        //输出代理的类型
        System.out.println("代理对象的类型:" + proxy.getClass());
    }
}
